<?php
	/**
	 * Loading basic functionality.
	 * @author IMP
	 */
	
	error_reporting(E_ALL); # Debugging

	define('DS', DIRECTORY_SEPARATOR, true);
	define('PATH_CORE', realpath(dirname(__FILE__)));
	define('PATH_CORE_CLASSES', realpath(dirname(__FILE__) . DS . 'classes'));
	define('PATH_CORE_DATABASES', realpath(dirname(__FILE__) . DS . 'databases'));
	define('PATH_CORE_CONFIGS', realpath(dirname(__FILE__) . DS . 'configurations'));
	define('PATH_DATA', realpath(dirname(__FILE__) . DS . '..' . DS . 'data'));
	define('PATH_APPS', realpath(dirname(__FILE__) . DS . '..' . DS . 'applications'));
	define('PATH_PUBLIC', realpath(dirname(__FILE__) . DS . '..' . DS . 'public'));
	define('URL_BASE', dirname($_SERVER['PHP_SELF']));
	define('URL_PUBLIC', dirname($_SERVER['PHP_SELF']) . '/public');
	
	abstract class ErrorCapturer {
		private static $errors = 0;
		
		public final static function getExceptionsCaught(){
			return self::$errors;
		}		
		
		public final static function __exception(Exception $e){
			self::$errors++;
			ob_end_clean();
			echo '<pre><b>Uncaught Exception: </b><br />' . $e . '</pre>';
		}
		
		public final static function __error($no, $str, $file, $line){
			ob_end_clean();
			throw new ErrorException($str, 0, $no, $file, $line);
			return false;
		}
	}
	
	set_error_handler(array('ErrorCapturer', '__error'));
	set_exception_handler(array('ErrorCapturer', '__exception'));
	
	function cc_include_once($f){ include_once $f; }
	function cc_include($f){ include $f; }
	function cc_require_once($f){ require_once $f; }
	function cc_require($f){ require $f; }
	
	class ClassNotFoundException extends Exception {
		public function __construct($class){
			parent::__construct('Class ' . $class . ' could not be found.');
		}
	}
	
	abstract class ClassLoader {
		private static $lookupPaths = array(PATH_CORE_CLASSES);
		
		public static final function addLookupPath($path){
			$path = realpath($path);
			if(is_dir($path)){
				self::$lookupPaths[$path] = $path;
			}
		}
		
		public static final function removeLookupPath($path){
			if(!empty(self::$lookupPaths[$path])) unset(self::$lookupPaths[$path]);
		}
		
		public static final function load($class){
			if(!class_exists($class)){
				foreach(self::$lookupPaths as $path){
					$search = $path . DS . $class . '.class.php';
					if(posix_access($search, POSIX_R_OK) && is_file($search)){
						cc_include_once($search);
						return true;
					}
				}
				
				throw new ClassNotFoundException($class);
			}
		}
		
		public static final function __autoload($class){
			try {
				self::load($class);
			}catch(ClassNotFoundException $e){}
		}
	}

	spl_autoload_register('ClassLoader::__autoload');
	
	$autoloadConfig = parse_ini_file(PATH_CORE_CONFIGS . DS . 'autoload.ini');
	if(!empty($autoloadConfig['path']) && is_array($autoloadConfig['path'])){
		foreach($autoloadConfig['path'] as $path){
			ClassLoader::addLookupPath($path);
		}
	}elseif(!empty($autoloadConfig['path']) && !is_array($autoloadConfig['path'])){
		ClassLoader::addLookupPath($autoloadConfig['path']);
	}
	unset($autoloadConfig);
	
	Extension::readExtensions(new File(PATH_CORE_CONFIGS . DS . 'extensions.ini', true));
?>